import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.util.PBounds;

public class BottomColorGridNode extends ColorGridNode {
	private final int DEFAULT_NUM_DAYS = 3;
	private final int DEFAULT_NUM_WEEKS = 3;
	private final int DEFAULT_ANIMATION_MILLIS = 250;
	private final float FOCUS_SIZE_PERCENT = 0.75f;

	private int numDays = DEFAULT_NUM_DAYS;
	private int numWeeks = DEFAULT_NUM_WEEKS;
	private int daysExpanded = 0;
	private int weeksExpanded = 0;
	
	private float hMin;
	private float hMax;
	private float bMin;
	private float bMax;
	private int[] gFilter;

	PCamera camera;
	ColorBoxNode focusedDay = null;
	PBounds prevCameraView;
	
	DbHandler db;

	public BottomColorGridNode(PCamera c, DbHandler d, float hm, float hM, float bm, float bM, int[] filter) {
		camera = c;
		db = d;
		hMin = hm;
		hMax = hM;
		bMin = bm;
		bMax = bM;
		gFilter = filter;
		float hStep = (hMax-hMin)/numDays;
		float bStep = (bMax-bMin)/numWeeks;
		float boxH = hMin;
		float boxB = bMax;
		
		for (int week = 0; week < numWeeks; week++) {
			for (int day = 0; day < numDays; day++) {
				addChild(new ColorBoxNode(camera, db, week, day, boxH, boxH+hStep, boxB-bStep, boxB, filter));
				boxH+=hStep;
			}
			boxH=hMin;
			boxB-=bStep;
		}

		BottomColorGridNode.this.addInputEventListener(new PBasicInputEventHandler() {
			@Override
			public void mouseReleased(PInputEvent event) {
				if (event.isLeftMouseButton() && !event.isShiftDown()) {
					ColorBoxNode pickedDay = (ColorBoxNode) event.getPickedNode();
					if (!pickedDay.hasWidthFocus()
							|| !pickedDay.hasHeightFocus()) {
						focusedDay = pickedDay;
						setFocusDayCopy(pickedDay, true);
					}
					event.setHandled(true);
				}
				else if (event.isRightMouseButton() && focusedDay != null) {
					focusedDay = null;
					BottomColorGridNode.this.setFocusDayCopy(null, true);
					if(prevCameraView != null)
						camera.animateViewToCenterBounds(prevCameraView, true, 500);
					event.setHandled(true);
				}
			}
		});
	}

	protected void setPrevCameraView(PBounds oldBounds) {
		prevCameraView = oldBounds;
	}

	public void setFilter(int[] filter){
		gFilter = filter;
		if(focusedDay != null){
			focusedDay.setFilter(filter);
		}
	}
	
	public ColorBoxNode getDayCopy(int week, int day) {
		return (ColorBoxNode) getChild((week * numDays) + day);
	}
	
	public void setFocusDayCopy(ColorBoxNode focusDay, boolean animate) {
		for (int i = 0; i < getChildrenCount(); i++) {
			ColorBoxNode each = (ColorBoxNode) getChild(i);
			each.setHasWidthFocus(false);
			each.setHasHeightFocus(false);
			each.setFilter(gFilter);
		}

		if (focusDay == null) {
			daysExpanded = 0;
			weeksExpanded = 0;
		} else {
			focusDay.setHasWidthFocus(true);
			daysExpanded = 1;
			weeksExpanded = 1;

			for (int i = 0; i < numDays; i++) {
				getDayCopy(focusDay.getWeek(), i).setHasHeightFocus(true);
			}

			for (int i = 0; i < numWeeks; i++) {
				getDayCopy(i, focusDay.getDay()).setHasWidthFocus(true);
			}			
		}
		if (focusDay != null)
			focusDay.prepareColorCount(gFilter);
		
		layoutChildren(focusDay, animate);
	}
	
	protected void layoutChildren(ColorBoxNode focusDay, boolean animate) {
		double focusWidth = 0;
		double focusHeight = 0;

		if (daysExpanded != 0 && weeksExpanded != 0) {
			focusWidth = (getWidth() * FOCUS_SIZE_PERCENT) / daysExpanded;
			focusHeight = (getHeight() * FOCUS_SIZE_PERCENT)
			/ weeksExpanded;
		}

		double collapsedWidth = (getWidth() - (focusWidth * daysExpanded))
		/ (numDays - daysExpanded);
		double collapsedHeight = (getHeight() - (focusHeight * weeksExpanded))
		/ (numWeeks - weeksExpanded);

		double xOffset = 0;
		double yOffset = 0;
		double rowHeight = 0;
		ColorBoxNode each = null;

		for (int week = 0; week < numWeeks; week++) {
			for (int day = 0; day < numDays; day++) {
				each = getDayCopy(week, day);
				double width = collapsedWidth;
				double height = collapsedHeight;

				if (each.hasWidthFocus())
					width = focusWidth;
				if (each.hasHeightFocus())
					height = focusHeight;

				if (animate) {
					each.animateToBounds(xOffset, yOffset, width, height,
							DEFAULT_ANIMATION_MILLIS).setStepRate(0);
				} else {
					each.setBounds(xOffset, yOffset, width, height);
				}

				xOffset += width;
				rowHeight = height;
			}
			xOffset = 0;
			yOffset += rowHeight;
		}
	}
}